package com.btcode.netty.server.handler.hrt;


import com.btcode.common.CRCUtil;
import com.btcode.common.PropertiesUnit;
import com.btcode.netty.server.handler.AbstractHrtDecoder;
import com.btcode.netty.server.session.util.ChannelUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

import java.util.List;

public class Hj212Decoder extends AbstractHrtDecoder {
    private final static boolean crcOff = "true".equals(PropertiesUnit.getValue("crcOff"));

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        try {
            //数据总长度
            int readableLength = in.readableBytes();
            if (readableLength < 12) {
                return;
            }
            in.markReaderIndex();

            //获取报文的长度
            byte[] dataLengthByte = new byte[4];
            //当前已读取的指针位置
            int readIndex = in.readerIndex();
            //获取长度部分报文的byte
            in.getBytes(readIndex + 2, dataLengthByte, 0, 4);
            //把长度部分报文的byte解析成string
            String dataLengthStr = new String(dataLengthByte);
            int dataLength;

            try {
                //把长度string解析成int，如果解析不成功，认为报文无效，清除掉
                dataLength = Integer.parseInt(dataLengthStr);
            }
            catch (Exception e) {
                in.clear();
                log.error(ChannelUtil.getIp(ctx.channel()) + "报文长度解析失败" + dataLengthStr, e);
                return;
            }

            if (dataLength < 1) {
                in.clear();
                return;
            }
            // ## + 四位长度 + 报文 + CRC验证码 + 回车换行符
            int expectDataLength = 2 + 4 + dataLength + 4 + 2;
            if (readableLength < expectDataLength) {
                //获取的数据长度和期望的长度不匹配，说明数据还没有接受完整，返回null等待数据
                in.resetReaderIndex();
                return;
            }
            //把解析完的数据放到输出流中
            ByteBuf re = in.readBytes(expectDataLength);
            if (!crcOff && !CRCUtil.match(getByteBufString(re))) {
                log.info(ChannelUtil.getIp(ctx.channel()) + "crc验证不通过", null);
                return;
            }
            out.add(re);
        }
        catch (Exception e) {
            log.error("报文粘拆包处理出错:" + getByteBufString(in), e);
        }
    }

    @Override
    public String getMnFromChannel(ChannelHandlerContext ctx, ByteBuf msgDecodeOut) {
        return getRegSplitValue("MN=(.+?);", getByteBufString(msgDecodeOut));
    }

    @Override
    public boolean[] shouldCheckConflictAndUseNewConn() {
        return new boolean[]{true, false};
    }
}